package com.retail.common.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * JWT工具类
 *
 * @author retail
 * @since 2024-01-01
 */
@Slf4j
@Component
public class JwtUtils {

  @Value("${jwt.secret:retail-platform-secret-key-2024-very-long-secret-key-for-jwt-security}")
  private String secret;

  @Value("${jwt.expiration:86400}")
  private Long expiration;

  /**
   * 生成JWT Token
   */
  public String generateToken(Map<String, Object> claims) {
    Date now = new Date();
    Date expiryDate = new Date(now.getTime() + expiration * 1000);

    return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(now)
        .setExpiration(expiryDate)
        .signWith(getSigningKey(), SignatureAlgorithm.HS512)
        .compact();
  }

  /**
   * 从Token中获取Claims
   */
  public Claims getClaimsFromToken(String token) {
    try {
      return Jwts.parserBuilder()
          .setSigningKey(getSigningKey())
          .build()
          .parseClaimsJws(token)
          .getBody();
    } catch (JwtException e) {
      log.error("解析JWT Token失败: {}", e.getMessage());
      return null;
    }
  }

  /**
   * 从Token中获取指定字段的值
   */
  public <T> T getClaimFromToken(String token, String claimName, Class<T> requiredType) {
    Claims claims = getClaimsFromToken(token);
    if (claims != null) {
      return claims.get(claimName, requiredType);
    }
    return null;
  }

  /**
   * 从Token中获取用户ID
   */
  public Long getUserIdFromToken(String token) {
    return getClaimFromToken(token, "userId", Long.class);
  }

  /**
   * 从Token中获取用户名
   */
  public String getUsernameFromToken(String token) {
    return getClaimFromToken(token, "username", String.class);
  }

  /**
   * 验证Token是否有效
   */
  public boolean validateToken(String token) {
    try {
      Jwts.parserBuilder()
          .setSigningKey(getSigningKey())
          .build()
          .parseClaimsJws(token);
      return true;
    } catch (JwtException e) {
      log.error("JWT Token验证失败: {}", e.getMessage());
      return false;
    }
  }

  /**
   * 检查Token是否过期
   */
  public boolean isTokenExpired(String token) {
    try {
      Claims claims = getClaimsFromToken(token);
      if (claims != null) {
        Date expiration = claims.getExpiration();
        return expiration.before(new Date());
      }
      return true;
    } catch (Exception e) {
      log.error("检查Token过期时间失败: {}", e.getMessage());
      return true;
    }
  }

  /**
   * 刷新Token
   */
  public String refreshToken(String token) {
    Claims claims = getClaimsFromToken(token);
    if (claims != null) {
      claims.setIssuedAt(new Date());
      return generateToken(claims);
    }
    return null;
  }

  /**
   * 获取签名密钥
   */
  private SecretKey getSigningKey() {
    byte[] keyBytes = secret.getBytes();
    // 确保密钥长度至少为512位（64字节）以支持HS512算法
    if (keyBytes.length < 64) {
      byte[] paddedKey = new byte[64];
      System.arraycopy(keyBytes, 0, paddedKey, 0, Math.min(keyBytes.length, 64));
      // 如果原密钥较短，用原密钥重复填充
      if (keyBytes.length < 64) {
        for (int i = keyBytes.length; i < 64; i++) {
          paddedKey[i] = keyBytes[i % keyBytes.length];
        }
      }
      keyBytes = paddedKey;
    }
    return Keys.hmacShaKeyFor(keyBytes);
  }
}
